//-----------------------------------------------------------------------
// <copyright file="MethodParameter.cs" company="iron9light">
//      Copyright (c) iron9light. All rights reserved.
// </copyright>
// <author>iron9light</author>
//-----------------------------------------------------------------------

namespace EventBrokerExtension
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// Base type for objects that are used to configure parameters for
    /// publication register.
    /// </summary>
    public abstract class MethodParameter
    {
        /// <summary>
        /// Gets the name for the type represented by this <see cref="MethodParameter"/>.
        /// This may be an actual type name or a generic argument name.
        /// </summary>
        /// <value>The name of the parameter type.</value>
        public abstract string ParameterTypeName
        {
            get;
        }

        /// <summary>
        /// Convert the given set of arbitrary values to a sequence of <see cref="MethodParameter"/>
        /// objects. The rules are: If it's already an <see cref="MethodParameter"/>, return it. If
        /// it's a Type, return a <see cref="TypedParameter"/> object for that type.
        /// </summary>
        /// <param name="values">The values to build the sequence from.</param>
        /// <returns>The resulting converted sequence.</returns>
        public static IEnumerable<MethodParameter> ToParameters(params object[] values)
        {
            foreach (object value in values)
            {
                yield return ToParameter(value);
            }
        }

        /// <summary>
        /// Test to see if this parameter value has a matching type for the given type.
        /// </summary>
        /// <param name="type">Type to check.</param>
        /// <returns>True if this parameter value is compatible with type <paramref name="type"/>,
        /// false if not.</returns>
        public abstract bool MatchesType(Type type);

        /// <summary>
        /// Convert an arbitrary value to an <see cref="MethodParameter"/> object. The rules are: 
        /// If it's already an <see cref="MethodParameter"/>, return it. If it's a Type, return a
        /// <see cref="TypedParameter"/> object for that type.
        /// </summary>
        /// <param name="value">The value to convert.</param>
        /// <returns>The resulting <see cref="MethodParameter"/>.</returns>
        private static MethodParameter ToParameter(object value)
        {
            MethodParameter methodParameter = value as MethodParameter;
            if (methodParameter != null)
            {
                return methodParameter;
            }

            Type typeValue = value as Type;
            if (typeValue != null)
            {
                return new TypedParameter(typeValue);
            }

            throw new ArgumentException(Properties.Resources.InvalidTypeOfParameterType, "value");
        }
    }
}
